********************************************************************************
*
* HENew - Allocates a new HexEdit record in the current port and returns the
*         HERecord defining that record. The parameters that define the HexEdit
*         record are specified in a HEParamBlock structure. HexEdit then
*         allocates and formats the HERecord for the new record.
*
*
*  PARAMETERS:
*
*  Stack before call
*
*         |________________|
*         |                |
*         |-              -|
*         |                |
*         |--   space    --| - Long - Result space.
*         |                |
*         |-              -|
*     $05 |________________|
*         |                |
*         |-              -|
*         |                |
*         |--  HEParam   --| - Long - Pointer to input HEParamBlock record.
*         |    BlockPtr    |
*         |-              -|
*     $01 |________________|
*         |                | <-SP
*
*  Stack after call
*
*         |________________|
*         |                |
*         |-              -|
*         |                |
*         |--   HEHand   --| - Long - Handle of newly created HERecord.
*         |                |
*         |-              -|
*     $01 |________________|
*         |                | <-SP
*

HENew               START

                    USING    HEGlobals

                    Debug    'HENew'

ResultHand          equ      $EC

                    ldx      #4              ;allocate dp space from stack
                    jsr      HESetup         ; and save caller's dp/b regs

                    pha
                    pha
                    _GetPort
                    PullLong CurPort          ;we need this to stuff into the rec

                    jsr      PushPortRectPtr
                    _GetPortRect

* Get the entire param block on our local dp so we can index it easily.

                    PushLong <HEParamBlockPtr ;source
                    PushWord #0
                    tdc
                    clc
                    adc      #HEParamBlock
                    pha                       ;dest
                    PushLong #HEParamBlockSize ;len
                    _BlockMove

* Make sure the pCount specified is within range.

                    ldx      #heInvalidPCount ;get an error code ready

                    lda      <pCount
                    cmp      #pCountMin      ;minimum pCount
                    blt      GoExitXReg

                    cmp      #pCountMax      ;maximum pCount+1
                    blt      PCountOK

GoExitXReg          ANOP

                    brl      HEExitXReg

PCountOK            ANOP

* Make sure that the reserved bits in the hexFlags field are not set. Also
* the fNotControl bit must be set since we don't support custom controls yet.

                    ldx      #heInvalidFlag  ;get an error code handy

                    lda      <hexFlags       ;the low word is currently
                    bne      GoExitXReg      ; completely reserved

                    lda      <hexFlags+2
                    and      #^fNotControl+fReserved28+fReserved25+fReserved16
                    cmp      #^fNotControl    ;must currently be set
                    bne      GoExitXReg      ;invalid bit specified

* Ok, everything looks fine. Grab a block for the new HERecord.

                    ldx      #0
                    ldy      #HERecordSize   ;size
                    lda      #0              ;attributes
                    jsr      NewAuxIDHandle
                    sty      HEHand
                    stx      HEHand+2

                    bcc      FillDefault

                    brl      HEExitAcc

* Fill in the new local HERecord with the default values since the caller may
* not be passing the maximum number of input parms.

FillDefault         ANOP

                    PushPtr  DefaultHERecord
                    PushWord #0
                    tdc
                    clc
                    adc      #HERecord
                    pha
                    PushLong #HERecordSize
                    _BlockMove

                    jsr      GetHERecordPtr  ;get a pointer to this new sucker

* Copy the user specified ID into the record.

                    lda      <ID
                    sta      <HERecord+octlID
                    lda      <ID+2
                    sta      <HERecord+octlID+2

* Now move the bounding rectangle into the record. If the bottom-right point is
* (0,0) then this means the record should fill to the lower right of the port.
* We also copy the new rectangle (expanded horizontally by 4 pixels, and
* vertically by 2 pixels) into PortRect for ease when building control rects.
* The expansion is for control creation so that they overlap with the bounds of
* the record.

                    lda      <rect+top
                    sta      <HERecord+octlRect+top
                    dec      a
                    sta      <PortRect+top

                    lda      <rect+left      ;so is the left
                    sta      <HERecord+octlRect+left
                    dec      a
                    dec      a
                    sta      <PortRect+left
                    iny
                    iny

                    lda      <rect+bottom    ;was a bottom specified?
                    bne      StuffVert       ; yep, stuff it

                    lda      <PortRect+bottom ; nope, use the port height

StuffVert           ANOP

                    sta      <HERecord+octlRect+bottom
                    inc      a
                    sta      <PortRect+bottom
                    iny
                    iny

                    lda      <rect+right     ;how about a right?
                    bne      StuffHorz       ; yep, plug it in

                    lda      <PortRect+right  ; no, use port height

StuffHorz           ANOP

                    sta      <HERecord+octlRect+right
                    inc      a
                    inc      a
                    sta      <PortRect+right

* Stuff the record owner's port into the record structure.

                    lda      <CurPort
                    sta      <HERecord+octlOwner
                    lda      <CurPort+2
                    sta      <HERecord+octlOwner+2

* Also copy the various flag fields into the record.

                    lda      <flag
                    sta      <HERecord+octlFlag

                    lda      <refCon
                    sta      <HERecord+octlRefCon
                    lda      <refCon+2
                    sta      <HERecord+octlRefCon+2

                    lda      <hexFlags
                    sta      <HERecord+ohexFlags
                    lda      <hexFlags+2
                    sta      <HERecord+ohexFlags+2

* Now we handle any optional fields that the caller specified.

                    lda      <pCount
                    sec
                    sbc      #8              ;min pCount+1
                    bpl      HandleOptionals

                    brl      GoScanFlags     ;no optional fields passed

HandleOptionals     ANOP

                    asl      a
                    tax
                    jmp      (OptionalParmsTable,x)

OptionalParmsTable  ANOP

                    DC       I2'DoHexDataRef'           ;parm 8
                    DC       I2'DoHexDataRef'           ;9
                    DC       I2'DoMaximumBytes'         ;10

DoMaximumBytes      ANOP

                    lda      <maximumBytes
                    sta      <HERecord+omaximumBytes
                    lda      <maximumBytes+2
                    sta      <HERecord+omaximumBytes+2

* The user can specify initial hex data in three ways; by pointer, handle, or
* resource ID. If no data is specified, don't allocate a storage block yet.
* If something is specified, copy it to a local handle, then stuff that handle
* into the HERecord.

DoHexDataRef        ANOP

                    lda      <hexDataRef     ;any initial data specified?
                    ora      <hexDataRef+2
                    beq      GoScanFlags     ; nope, parse the spec bits

                    ldy      <hexDataRef     ;get the reference to inital hex data
                    ldx      <hexDataRef+2

* Determine in what form the initial hex data was passed to us.

                    lda      <moreFlags
                    and      #$0003          ;mask lower two bits
                    beq      ItsAPtr         ;easy, we already have a pointer

                    dec      a
                    beq      ItsAHandle     ;we've got a handle, deref

                    dec      a
                    beq      ItsAResource   ;yech, a resID :-)

                    lda      #heInvalidDescriptor ;what in the world was that?

GoExitAcc           ANOP

                    brl      HEExitAcc

ItsAResource        ANOP

                    stx      resIDRD+2
                    sty      resIDRD
                    lda      <hexDataResTypeRef
                    sta      resTypeRD

                    _fLoadResource fResDataRec

;                   pha
;                   pha
;                   PushWord <hexDataResTypeRef ;resourceType
;                   phx
;                   phy                      ;resourceID
;                   _LoadResource

                    bcs      GoExitAcc

                    ldy      resDataRD
                    ldx      resDataRD+2

ItsAHandle          ANOP

                    phx                      ;for deref below
                    phy

                    pha
                    pha
                    phx
                    phy
                    _GetHandleSize
                    PullLong hexDataLength

                    jsr      DerefHand
                    tay                      ;ptr low

ItsAPtr             ANOP

                    phx
                    phy                      ;source for data copy

* Get a new block for the initial hex data.

                    ldx      <hexDataLength+2
                    ldy      <hexDataLength  ;length
                    lda      #0              ;attributes
                    jsr      NewAuxIDHandle

                    bcs      GoExitAcc

                    phx                      ;dest handle
                    phy

                    sty      <HERecord+ohexDataHand ;save the handle into the record
                    stx      <HERecord+ohexDataHand+2

                    PushLong <hexDataLength
                    _PtrToHand               ;copy the initial data to our block

GoScanFlags         ANOP

                    jsr      ScanHexFlags    ;build controls based on hexFlags bits

ExitHENew           ANOP

                    jsr      CopyLocalsToHERec ;copy our dp rec to the caller's new block

                    lda      <HEHand         ;I guess it would be best to let
                    sta      <ResultHand     ; the caller know where the record
                    lda      <HEHand+2       ; is. :-)
                    sta      <ResultHand+2

                    lda      #0              ;no error

                    brl      HEExitAcc       ;later dudeskies

                    END